Home:ALL Converter>Could it be that (Alternative f, Foldable f) => Monad f?

Could it be that (Alternative f, Foldable f) => Monad f?

Ask Time:2017-05-24T19:19:28         Author:user1747134

Json Formatter

The following typechecks:

instance (Applicative f, Alternative f, Foldable f) => Monad f where 
  (>>=) = flip $ \f -> foldr (<|>) empty . fmap f
  -- Or equivalently
  a >>= b = getAlt . foldMap Alt . fmap b $ a

Is this actually a valid Monad instance? If yes, why is it not used? If no, does it break any laws or such? I have not proved that the laws hold, but I couldn't find a counterexample either.

Author:user1747134,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/44156863/could-it-be-that-alternative-f-foldable-f-monad-f
chi :

This should be a counterexample to the right identity monad law.\n\nBelow, we exploit the functor product Maybe :*: Maybe from GHC.Generics, but it could be inlined, if wished. This is also an applicative, alternative, foldable, and monad. I trust the libraries on these instances to be law-abiding.\n\nWe then compare the proposed instance Monad (the one in the question) to the standard library one. We find that the right identity law is not satisfied for the proposed instance, while it appears to hold (at least in my very limited tests) in the library instance.\n\n{-# LANGUAGE FlexibleInstances, GeneralizedNewtypeDeriving, TypeOperators #-}\n{-# OPTIONS -Wall #-}\n\nmodule NotAMonad where\n\nimport Control.Applicative\nimport GHC.Generics ((:*:)(..))\n\n-- A basic wrapper to avoid overlapping instances, and to be able to\n-- define a custom monad instance.\nnewtype Wrap m a = Wrap { unWrap :: m a }\n deriving (Functor, Applicative, Alternative, Foldable, Show)\n\n-- The proposed instance\ninstance (Applicative f, Alternative f, Foldable f) => Monad (Wrap f) where \n (>>=) = flip $ \\f -> foldr (<|>) empty . fmap f\n\n-- This is Applicative, Alternative, and Foldable\ntype T = Maybe :*: Maybe\n\n-- A basic test\ntest :: Wrap T Int\ntest = Wrap (Just 3 :*: Just 4) >>= return\n-- result:\n-- Wrap {unWrap = Just 3 :*: Just 3}\n\n\nThe 4 is now replaced by 3. I have not tried to explain why, though.\nI guess it is caused by Just 3 <|> Just 4 = Just 3.\n\nUsing the library monad instance, instead, everything looks fine:\n\n> (Just 3 :*: Just 4) >>= return\nJust 3 :*: Just 4\n",
2017-05-24T11:35:49
yy